package com.atguigu.linkedlist;

/**
 * 双向链表的实现
 *
 * @author WangJX
 * @version 1.0
 * @date 2019/9/22 16:10
 */
public class DoubleLinkedListDemo {
    public static void main(String[] args) {
        HeroNode2 heroNode1 = new HeroNode2(1, "宋江", "及时雨");
        HeroNode2 heroNode2 = new HeroNode2(2, "卢俊义", "玉麒麟");
        HeroNode2 heroNode3 = new HeroNode2(3, "吴用", "智多星");

        HeroNode2 heroNode4 = new HeroNode2(4, "公孙胜", "入云龙");
        HeroNode2 heroNode5 = new HeroNode2(5, "关胜", "大刀");
        HeroNode2 heroNode6 = new HeroNode2(6, "林冲", "豹子头");


        DoubleLinkedList list1 = null;
        DoubleLinkedList list2 = null;

        try {
            list1 = new DoubleLinkedList();

//            list1.add(heroNode1);
//            list1.add(heroNode2);
//            list1.add(heroNode3);

            list1.addById(heroNode3);
            list1.addById(heroNode1);
            list1.addById(heroNode5);

            list1.addById(heroNode4);
            list1.addById(heroNode2);
            list1.addById(heroNode6);

        } catch (Exception e) {
            e.printStackTrace();
        }

        //修改单链表
        HeroNode2 heroNode = new HeroNode2(6, "小吴", "诸葛亮");
        list1.updata(heroNode);

        //删除数据
//        list1.delete(3);
        list1.delete(1);
        list1.delete(6);

        list1.list();

        System.out.println("反转链表：");
        list1.reverseList();
    }
}

class DoubleLinkedList {
    //先初始化一个头结点
    private HeroNode2 head;
    private HeroNode2 end;

    /**
     * 双链表添加
     *
     * @param heroNode 要添加的数据
     */
    public void add(HeroNode2 heroNode) {
        HeroNode2 temp = head;
        //判断是不是第一次添加数据
        if (head == null) {
            head = heroNode;
            return;
        }

        //遍历链表，找到最后一位数据
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        //把数据指向下一位
        temp.next = heroNode;
        heroNode.pre = temp;
        end = heroNode;
    }

    /**
     * 双向链表修改
     *
     * @param newheroNode 要修改的数据，根据id进行匹配
     */
    public void updata(HeroNode2 newheroNode) {
        if (head == null) {
            throw new RuntimeException("链表为空!");
        }
        HeroNode2 temp = head;
        boolean flag = false;
        while (true) {
            //如果下一个节点信息为null，代表已经到了链表的最后
//            if (temp.next == null) {
//                break;
//            }

            //如果temp的id和要修改的id相等，说明找到了要修改的节点
            if (temp.id == newheroNode.id) {
                flag = true;
                break;
            }

            temp = temp.next;
        }
        //如果flag为true，说明找了要修改的节点
        if (flag) {
            temp.name = newheroNode.name;
            temp.nickname = newheroNode.nickname;
        } else {
            throw new RuntimeException("没有该id的节点");
        }

    }


    /**
     * 删除双向链表
     *
     * @param id 要删除数据的id
     */
    public void delete(int id) {
        if (head == null) {
            throw new RuntimeException("链表为空!");
        }

        HeroNode2 temp = head;
        boolean flag = false;
        while (true) {
            if (temp == null) {
                break;
            }
            if (temp.id == id) {
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag) {
            //判断要删除的节点是否是第一个
            if (head.id == id) {
                head.next.pre = null;
                head = head.next;
            }else if (end.id == id){    //判断要删除的节点是否是最后一个节点
                end.pre.next = null;
                end = end.pre;
            }else { //删除其他节点
                temp.pre.next = temp.next;
                temp.next.pre = temp.pre;
            }
        } else {
            throw new RuntimeException("没有要删除的id!");
        }
    }


    /**
     * 双向链表顺序插入
     *
     * @param heroNode 要插入的数据(根据id顺序插入)
     */
    public void addById(HeroNode2 heroNode) {

        //判断是否第一次添加数据
        if (head == null) {
            head = heroNode;
            end = heroNode;
            return;
        }

        HeroNode2 temp = head;
        boolean flag = false;

        while (true) {
            //当数据遍历到最后一位还不满足，就添加到最后
            if (temp == null) {
                break;
            }
            //当temp后一位的id大于要插入的id，说明已经找到了要插入的位置
            if (temp.id > heroNode.id) {
                break;
            } else if (temp.id == heroNode.id) {   //当要插入的id等于找到位置后一位的id，说明id重复
                flag = true;
                break;
            }

            if (temp.next != null) {
                temp = temp.next;
            } else {
                break;
            }
        }
        //判断id是否重复，重复给出提示，不重复插入数据
        if (flag) {
            throw new RuntimeException("要添加的id重复：" + heroNode.id);
        } else {
            //数据放入最后一位
            if (temp.next == null && temp.id < heroNode.id) {
                temp.next = heroNode;
                heroNode.pre = temp;
                end = heroNode;
            } else if (temp.id > heroNode.id) { //数据往前插入
                //判断要添加的数据是否放在头节点
                if(temp.pre == null) {
                    heroNode.next = head;
                    head.pre = heroNode;
                    head = heroNode;
                }else {
                    heroNode.pre = temp.pre;
                    temp.pre.next = heroNode;
                    heroNode.next = temp;
                    temp.pre = heroNode;
                }
            } else if (temp.id < heroNode.id) {  //数据往后插入
                heroNode.pre = temp;
                heroNode.next = temp.next;
                temp.next.pre = heroNode;
                temp.next = heroNode;
            }
        }


    }

    /**
     * 双向链表遍历
     */
    public void list() {
        if (head == null) {
            System.out.println("链表为空");
            return;
        }

        HeroNode2 temp = head;
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }

    /**
     * 双向链表反向输出
     */
    public void reverseList() {
        if (end == null) {
            System.out.println("链表为空");
            return;
        }

        HeroNode2 temp = end;
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp);
            temp = temp.pre;
        }

    }


    public HeroNode2 getHead() {
        return head;
    }

    public HeroNode2 getEnd() {
        return end;
    }
}

class HeroNode2 {
    public int id;
    public String name;
    public String nickname;
    public HeroNode2 next;
    public HeroNode2 pre;

    public HeroNode2(int id, String name, String nickname) {
        this.id = id;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "id=" + id +
                ", name=" + name +
                ", nickname=" + nickname;
    }
}